package event

import (
	"errors"
	"fmt"
	"io"
	"log/slog"
	"reflect"
)

type Event struct {
	processList []interface{}
}

func NewEvent() *Event {
	return &Event{processList: make([]interface{}, 0)}
}

func (e *Event) ProcessList() []interface{} {
	return e.processList
}

func (e *Event) Register(proc any) {
	switch proc := proc.(type) {
	case Process, AcceptProcess, DisconnectProcess:
		e.processList = append(e.processList, proc)
		slog.Debug("register Processor " + reflect.TypeOf(proc).String())
	default:
		slog.Error("processor type mismatch", "type", reflect.TypeOf(proc).String())
	}
}

func (e *Event) UnRegister(proc Process) {
	for index, process := range e.processList {
		if proc == process {
			e.processList = append(e.processList[:index], e.processList[index+1:]...)
			return
		}
	}
}

func (e *Event) execute(session *Session, body any) (result any, err error) {
	if e.processList == nil || len(e.processList) == 0 {
		return nil, errors.New("process list is empty")
	}

	for i, process := range e.processList {
		session.Logger.Debug("execute Process " + reflect.TypeOf(process).String())
		if session.state == Accept {
			if handler, ok := process.(AcceptProcess); ok {
				err = handler.Accept(session)
			}
		}
		if session.state == Disconnect {
			if handler, ok := process.(DisconnectProcess); ok {
				err = handler.Disconnect(session)
			}
		}
		if session.state == Active {
			if handler, ok := process.(Process); ok {
				if i == 0 {
					// 执行第一个处理器, 使用函数实参
					result, err = handler.Active(session, body)
				} else {
					// 执行非第一个处理器, 使用链式参数(前个处理器返回值, 作为下个处理器入参)
					result, err = handler.Active(session, result)
				}
			}
		}

		if err == io.EOF {
			return result, err
		} else if err != nil {
			processName := reflect.ValueOf(process).Elem().Type().String()
			return nil, fmt.Errorf("%s: %s", processName, err.Error())
		}
	}
	return result, nil
}
